#!/usr/bin/env python3.9
# encoding: utf-8

import os
import time
import subprocess
import conf
import IPy
from utils import install_helm3,format_print

# 验证输入 ip地址的格式
def check_params(input_value):
    if not input_value:
        exit('输入有误')
    ip_list = input_value.split(',')
    for ip_addr in ip_list:
        try:
            IPy.IP(ip_addr)
        except Exception as e:
            exit(e)


class KubernetesInstall(object):
    def __init__(self, master_ip, node_ip):
        self.master_ip = master_ip
        self.node_ip = node_ip

    # 初始化安装环境
    @staticmethod
    def init_shell():
        return conf.INIT_SHELL_LIST

    # 安装ingress
    @staticmethod
    def install_ingress():
        format_print(string='安装ingress-controller...')
        os.system("kubectl apply -f %s/k8s-yaml/ingress-nginx.yaml >/dev/null 2>&1" % conf.BASE_DIR)
        format_print(string='ingress-controller组件安装完成',mode=False)

    @staticmethod
    # 安装jenkins
    def install_jenkins():
        os.system("mkdir /nfs/data/jenkins > /dev/null 2>&1")  # 创建jenkins挂载目录
        format_print(string='安装jenkins...')
        os.system("kubectl apply -f %s/k8s-yaml/jenkins/. > /dev/null 2>&1" % conf.BASE_DIR)
        time.sleep(1)
        format_print(string='jenkins部署完成,等待状态running，即可登陆网址访问 http://ip:nodeport',mode=False)
        format_print(string='执行 cat /nfs/data/jenkins/secrets/initialAdminPassword 输入访问密钥',mode=False)


    # 安装nfs
    @staticmethod
    def install_nfs():
        # 主节点配置nfs
        os.system("echo '/nfs/data/ *(insecure,rw,sync,no_root_squash)' > /etc/exports")
        os.system("systemctl enable rpcbind --now > /dev/null 2>&1")
        os.system("systemctl enable nfs-server --now >/dev/null 2>&1")
        os.system("exportfs -r")

    # 安装dashboard
    @staticmethod
    def install_dashboard():
        # Master节点部署UI
        format_print(string='正在安装dashboard...')
        recommended = os.system("kubectl apply -f %s/k8s-yaml/recommended.yaml > /dev/null 2>&1" % conf.BASE_DIR)
        admin_user_sa = os.system("kubectl apply -f %s/k8s-yaml/dash.yaml > /dev/null 2>&1" % conf.BASE_DIR)  # 创建管理员账号访问dashboard
        dashboard_token = os.system(
            "kubectl describe secret -n kubernetes-dashboard ` kubectl get secret -n kubernetes-dashboard | grep admin-user-token | awk '{print $1}'` | grep 'token' | awk 'NR==3{print $2}' > /etc/kubernetes/admin-token.txt")
        format_print(string='dashboard安装完成',mode=False)
        format_print(string='使用/etc/kubernetes/admin-token.txt 中的密钥进行认证',mode=False)

    # 安装动态存储卷
    @staticmethod
    def install_nfs_client_provisioner():
        format_print(string='安装nfs-client-provisioner...')
        os.system("kubectl create ns storage > /dev/null 2>&1")
        os.system("kubectl apply -f %s/k8s-yaml/nfs-client-provisioner.yaml > /dev/null 2>&1 " % conf.BASE_DIR)
        format_print(string='nfs-client-provisioner组件安装完成',mode=False)

    # 安装prometheus
    @staticmethod
    def install_prometheus():
        format_print(string='开始安装prometheus...')
        # 1. 部署 node-exporter 组件
        os.system("kubectl apply -f %s/k8s-yaml/node-exporter-ds.yaml >/dev/null 2>&1" % conf.BASE_DIR)
        # 2. 配置prometheus server
        os.system("kubectl apply -f %s/k8s-yaml/prometheus/. >/dev/null 2>&1" % conf.BASE_DIR)
        format_print(string='prometheus安装完成',mode=False)


    def install_apps(self):
        self.install_dashboard()
        self.install_nfs()
        self.install_ingress()
        # self.install_nfs_client_provisioner()
        self.install_prometheus()
        self.install_jenkins()
        install_helm3(conf.HELM_VERSION)

    #  安装从节点
    def install_nodes(self, masterip, node_ip_list, token_create_res, token_code_res, node_num):
        for node in node_ip_list:
            #  拷贝master节点的hosts文件到node节点上
            os.system("scp -rp /etc/hosts %s:/etc/hosts" % node)
            print("\033[34;1m*\033[0m" * 20, "\033[34;1m 当前操作节点node,IP: %s\033[0m" % node)
            node_num += 1
            # 设置主机名
            node_name = "node0%s" % node_num
            host_node_name = os.system("ssh %s hostnamectl set-hostname %s" % (node, node_name))

            format_print(string='初始化node节点环境...')
            for shell in self.init_shell():
                time.sleep(1)
                try:
                    os.system("ssh %s \"%s\" " % (node, shell))
                except Exception as e:
                    print(e)
                    exit()
            format_print(string='初始化环境完成',mode=False)
            print("*" * 20, "%s正在加入集群..." % node_name)
            print("\033[32;1m*\033[0m" * 20, "\033[32;1m %s正在加入集群...\033[0m" % node_name)
            print("token_creat : ", token_create_res)
            print("token_code : ", token_code_res)
            kubeadm_join = os.system(
                "ssh %s \" kubeadm join %s:6443 --token %s --discovery-token-ca-cert-hash sha256:%s\" > /dev/null 2>&1" % (
                    node, masterip, str(token_create_res), str(token_code_res)))
            format_print(string='加入集群成功',mode=False)
            format_print(string='执行以下命令,检查K8s集群\n',mode=False)
            format_print(string='kubectl get nodes',mode=False)
            format_print(string='kubectl get cs',mode=False)
            format_print(string='kubectl get pod -n kube-system',mode=False)


    #  执行命令 安装主节点
    def shell_command(self):
        master_ip_list = self.master_ip.split(',')
        node_ip_list = self.node_ip.split(',')
        token_create = ()
        token_node = ()
        hostname_num = 0  # 主机名序号
        node_num = 0  # node名序号
        for master in master_ip_list:
            hostname_num += 1
            hosts_name = ""
            if master == master_ip_list[0]:  # 判断是当前master单节点
                print("\033[34;1m*\033[0m" * 20, "\033[34;1m 当前操作节点master,IP: %s\033[0m"%master)
                format_print(string='配置hosts...')
                # 设置主机名
                master_name = "master0%s" % hostname_num
                host_name = os.system('hostnamectl set-hostname %s' % master_name)
                # 添加host文件
                master_host = master + "  " + master_name
                etc_hosts = os.system("echo '%s' >> /etc/hosts" % master_host)

                # 添加node节点的host
                for hosts in node_ip_list:
                    hostname_num += 1
                    hosts_name += hosts + " node0%s" % (hostname_num - 1) + "\n"
                os.system("cat >> /etc/hosts <<EOF \n%sEOF\n" % hosts_name)
                format_print(string='hosts配置完成',mode=False)
                # 初始化集群
                format_print(string='开始环境初始化，请耐心等待...')

                for shell in self.init_shell():
                    time.sleep(1)
                    try:
                        init_env = os.system(shell)
                    except Exception as e:
                        print(e)
                        exit()
                format_print(string='初始化完成，开始进行kubernetes集群安装',mode=False)
                kubeadm_init = os.system(
                    "kubeadm init --kubernetes-version=%s --image-repository %s  --service-cidr=%s "
                    "--pod-network-cidr=%s --apiserver-advertise-address=%s  > /dev/null 2>&1" % ((
                        conf.KUBERNETES_VERSION, conf.IMAGES_REPOSITORY, conf.SERVICE_CIDR, conf.POD_NETWORK_CIDR,
                        master)))
                format_print(string='创建.kube文件，并拷贝配置文件admin.conf')
                mkdir_kube = os.system("mkdir -p /root/.kube")
                kube_config = os.system("cp -i /etc/kubernetes/a"
                                        "dmin.conf /root/.kube/config")

                # 部署 网络组建calico 或 flannel
                format_print(string='开始安装部署网络组建 calico...')
                apply_calico = os.system("kubectl apply -f k8s-yaml/calico.yaml > /dev/null 2>&1")
                format_print(string='网络组件calico安装完成',mode=False)

                # 获取加入集群的 token 和校验字符串 kubeadm join cluster-endpoint:6443 --token hums8f.vyx71prsg74ofce7
                # --discovery-token-ca-cert-hash
                # sha256:a394d059dd51d68bb007a532a037d0a477131480ae95f75840c461e85e2c6ae3"""
                token_create = subprocess.getstatusoutput("kubeadm token create")
                token_code = subprocess.getstatusoutput("openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl "
                                                        "rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex "
                                                        "| sed 's/^.* //'")

                token_create_res = token_create[1].split('\n')[-1]
                token_code_res = token_code[-1]

                # 安装从节点，要保证master节点做了免密登陆其他node节点
                self.install_nodes(master, node_ip_list, token_create_res, token_code_res, node_num)
                self.install_apps()

            else:  # 否则就是集群模式
                exit()


if __name__ == '__main__':
    master_ip = input('输入k8s集群master的ip地址，如果有多个则以逗号隔开 如[1.1.1.1,2.2.2.2,... ]:')
    check_params(master_ip)
    node_ip = input('输入k8s集群node的ip地址，如果有多个则以逗号隔开 如[1.1.1.1,2.2.2.2,... ]:')
    check_params(node_ip)
    k8s_install = KubernetesInstall(master_ip, node_ip)
    k8s_install.shell_command()
